﻿using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace IoTSignalR
{
    public class AnonymousPipeServer
    {
     
        public ConcurrentDictionary<string, AnonymousPipeServerStream> _writerClients = new ConcurrentDictionary<string, AnonymousPipeServerStream>();
        public ConcurrentDictionary<string, AnonymousPipeServerStream> _readerClients = new ConcurrentDictionary<string, AnonymousPipeServerStream>();
        private readonly string childProcessPath;
        //信号量=》卡槽=》限制线程数量
        private readonly SemaphoreSlim semaphoreSlim;

        public event EventHandler<NotifyEventArg> SendMessageAfter;
        public event EventHandler<NotifyEventArg> ReceiveMessagesAfter;
        public event EventHandler<NotifyEventArg> OnConnected;
        public event EventHandler<NotifyEventArg> OnDisconnected;
        public event EventHandler<NotifyEventArg> OnReceiveErro;
        public event EventHandler<NotifyEventArg> OnSendErro;
        public event EventHandler<string> OnBusError;
        public AnonymousPipeServer(string childProcessPath,int maxConnectionCount)
        {
            this.childProcessPath = childProcessPath;
            this.semaphoreSlim = new SemaphoreSlim(maxConnectionCount);
        }
        public void Start()
        {
            Task.Run(async () =>await ListenInPipeServer());
            async Task ListenInPipeServer()
            {
                // 服务端
                while (true)
                {
                    try
                    {
                        await semaphoreSlim.WaitAsync();
                        //这一侧是写入
                        var anonymousPipeServerStreamWriter = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable);
                        var anonymousPipeServerStreamReader = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable);

                        // 获取管道句柄
                        string handleWriter = anonymousPipeServerStreamWriter.GetClientHandleAsString();
                        string handleReader = anonymousPipeServerStreamReader.GetClientHandleAsString();

                        // 启动子进程，并传递管道句柄
                        Process childProcess = new Process
                        {
                            StartInfo = new ProcessStartInfo
                            {
                                FileName = childProcessPath, // 子进程可执行文件
                                Arguments = $"{handleWriter}${handleReader}", // 传递管道句柄
                                UseShellExecute = false, // 禁用 Shell 执行
                                RedirectStandardOutput = false, // 重定向子进程输出（便于调试）
                                RedirectStandardError = false  // 重定向子进程错误（便于调试）
                            }
                        };
                        childProcess.Start();

                        // 关闭服务端的句柄副本，避免资源泄漏
                        //anonymousPipeServerStreamWriter.DisposeLocalCopyOfClientHandle();
                        //anonymousPipeServerStreamReader.DisposeLocalCopyOfClientHandle();

                        //
                        var clientId = Guid.NewGuid().ToString();
                        _writerClients[clientId] = anonymousPipeServerStreamWriter;
                        _readerClients[clientId] = anonymousPipeServerStreamReader;
                        OnConnected?.Invoke(this, new NotifyEventArg(clientId, "管道创建"));
                        //
                        _ = Task.Run(async () =>await HandleClient(clientId, anonymousPipeServerStreamWriter, anonymousPipeServerStreamReader, childProcess));
                    }
                    catch (Exception ex)
                    {
                        OnBusError?.Invoke(this, ex.Message);
                        semaphoreSlim.Release();
                    }
                }
                async Task HandleClient(string clientId, 
                    AnonymousPipeServerStream anonymousPipeServerStreamWriter, AnonymousPipeServerStream anonymousPipeServerStreamReader,
                    Process process)
                {
                    try
                    {
                        while (anonymousPipeServerStreamReader.IsConnected)
                        {
                            byte[] buffer = new byte[1024];
                            int bytesRead = await anonymousPipeServerStreamReader.ReadAsync(buffer, 0, buffer.Length);
                            if (bytesRead > 0)
                            {
                                string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                                ReceiveMessagesAfter?.Invoke(this, new NotifyEventArg(clientId, message));
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        OnReceiveErro?.Invoke(this, new NotifyEventArg(clientId, ex.Message));
                    }
                    finally
                    {
                        //子进程退出
                        if (!process.HasExited)
                        {
                            process.Kill();
                        }
                        process.Dispose(); 
                        //管道断开连接
                        this.OnDisconnected.Invoke(this, new NotifyEventArg(clientId, "客户端离开"));
                        _writerClients.TryRemove(clientId, out _);
                        _readerClients.TryRemove(clientId, out _);
                        anonymousPipeServerStreamWriter.Dispose();
                        anonymousPipeServerStreamReader.Dispose();
                        //卡槽释放一位
                        semaphoreSlim.Release();
                    }
                }
            }
        }
        public async Task SendMessage(string clientId, string msg)
        {
            try
            {
                if (_writerClients.TryGetValue(clientId, out var namedPipeServerStream))
                {
                    if (namedPipeServerStream.IsConnected)
                    {
                        byte[] bufferBack = Encoding.UTF8.GetBytes(msg);
                        await namedPipeServerStream.WriteAsync(bufferBack, 0, bufferBack.Length);
                        await namedPipeServerStream.FlushAsync();
                        SendMessageAfter?.Invoke(this, new NotifyEventArg(clientId, msg));
                        //消息记录，消息记数。。。。。。
                    }
                    else
                    {
                        SendMessageAfter?.Invoke(this, new NotifyEventArg(clientId, "客户端未连接"));
                        //消息记录，消息记数。。。。。。
                    }
                }
                else
                {
                    SendMessageAfter?.Invoke(this, new NotifyEventArg(clientId, "客户端已离开"));
                    //消息记录，消息记数。。。。。。
                }

            }
            catch (Exception ex)
            {
                OnSendErro?.Invoke(this, new NotifyEventArg(clientId, ex.Message));
            }
        }
        public async Task SendGroupMessage(string clientId, string msg)
        {
            try
            {
                foreach (var client in _writerClients)
                {
                    if (client.Key != clientId)
                    {
                        if (client.Value.IsConnected)
                        {
                            byte[] bufferBack = Encoding.UTF8.GetBytes(msg);
                            await client.Value.WriteAsync(bufferBack, 0, bufferBack.Length);
                            await client.Value.FlushAsync();

                        }

                    }
                }
                SendMessageAfter?.Invoke(this, new NotifyEventArg(clientId, "群发消息" + msg));
                //消息记录，消息记数。。。。。。
            }
            catch (Exception ex)
            {
                OnSendErro?.Invoke(this, new NotifyEventArg(clientId, ex.Message));
            }
        }
    }
}
